#pragma once

#ifndef __CORE_Event_H__
#define __CORE_Event_H__

#include "FLOW_core/container_types.h"
#include "FLOW_core/Delegate.h"
#include "FLOW_core/namespace.h"

namespace CORE
{
	// Defines for template specialization
	#undef RETURN_TYPE
	#undef RETURN_TYPE_TEMPLATE
	#undef COMMA_SEPARATOR
	#undef ARGUMENTS_TYPES
	#undef ARGUMENTS_TYPES_TEMPLATE
	#undef ARGUMENTS_TYPES_NAMES
	#undef ARGUMENTS_NAMES
	#undef ARGUMENTS_SPECIALIZATION

	#define RETURN_TYPE					ReturnType
	#define RETURN_TYPE_TEMPLATE		typename RETURN_TYPE
	#define COMMA_SEPARATOR
	#define ARGUMENTS_TYPES				void
	#define ARGUMENTS_TYPES_TEMPLATE
	#define ARGUMENTS_TYPES_NAMES
	#define ARGUMENTS_NAMES
	#define ARGUMENTS_SPECIALIZATION

	// Set the defines value to create all the specializations needed ( n arguments )
	#undef RETURN_TYPE
	#undef RETURN_TYPE_TEMPLATE
	#undef COMMA_SEPARATOR
	#undef ARGUMENTS_TYPES
	#undef ARGUMENTS_TYPES_TEMPLATE
	#undef ARGUMENTS_TYPES_NAMES
	#undef ARGUMENTS_NAMES
	#undef ARGUMENTS_SPECIALIZATION

	#define RETURN_TYPE					ReturnType
	#define RETURN_TYPE_TEMPLATE		typename RETURN_TYPE
	#define COMMA_SEPARATOR				,
	#define ARGUMENTS_TYPES				Arg1Type, Arg2Type, Arg3Type, Arg4Type, Arg5Type, Arg6Type, Arg7Type, Arg8Type, Arg9Type, Arg10Type
	#define ARGUMENTS_TYPES_TEMPLATE	typename Arg1Type = NullType, typename Arg2Type = NullType, typename Arg3Type = NullType, typename Arg4Type = NullType, typename Arg5Type = NullType, typename Arg6Type = NullType, typename Arg7Type = NullType, typename Arg8Type = NullType, typename Arg9Type = NullType, typename Arg10Type = NullType
	#define ARGUMENTS_TYPES_NAMES		Arg1Type a1, Arg2Type a2, Arg3Type a3, Arg4Type a4, Arg5Type a5, Arg6Type a6, Arg7Type a7, Arg8Type a8, Arg9Type a9, Arg10Type a10
	#define ARGUMENTS_NAMES				a1, a2, a3, a4, a5, a6, a7, a8, a9, a10
	#define ARGUMENTS_SPECIALIZATION

	#include "Event_template.h"

	// 0 arguments specialization

	#undef RETURN_TYPE
	#undef RETURN_TYPE_TEMPLATE
	#undef COMMA_SEPARATOR
	#undef ARGUMENTS_TYPES
	#undef ARGUMENTS_TYPES_TEMPLATE
	#undef ARGUMENTS_TYPES_NAMES
	#undef ARGUMENTS_NAMES
	#undef ARGUMENTS_SPECIALIZATION

	#define RETURN_TYPE					ReturnType
	#define RETURN_TYPE_TEMPLATE		typename RETURN_TYPE
	#define COMMA_SEPARATOR
	#define ARGUMENTS_TYPES
	#define ARGUMENTS_TYPES_TEMPLATE
	#define ARGUMENTS_TYPES_NAMES
	#define ARGUMENTS_NAMES
	#define ARGUMENTS_SPECIALIZATION	< RETURN_TYPE, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType >

	#include "Event_template.h"

	// 1 arguments specialization

	#undef RETURN_TYPE
	#undef RETURN_TYPE_TEMPLATE
	#undef COMMA_SEPARATOR
	#undef ARGUMENTS_TYPES
	#undef ARGUMENTS_TYPES_TEMPLATE
	#undef ARGUMENTS_TYPES_NAMES
	#undef ARGUMENTS_NAMES
	#undef ARGUMENTS_SPECIALIZATION

	#define RETURN_TYPE					ReturnType
	#define RETURN_TYPE_TEMPLATE		typename RETURN_TYPE
	#define COMMA_SEPARATOR				,
	#define ARGUMENTS_TYPES				Arg1Type
	#define ARGUMENTS_TYPES_TEMPLATE	typename Arg1Type
	#define ARGUMENTS_TYPES_NAMES		Arg1Type a1
	#define ARGUMENTS_NAMES				a1
	#define ARGUMENTS_SPECIALIZATION	< RETURN_TYPE, Arg1Type, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType >

	#include "Event_template.h"

	// 2 arguments specialization

	#undef RETURN_TYPE
	#undef RETURN_TYPE_TEMPLATE
	#undef COMMA_SEPARATOR
	#undef ARGUMENTS_TYPES
	#undef ARGUMENTS_TYPES_TEMPLATE
	#undef ARGUMENTS_TYPES_NAMES
	#undef ARGUMENTS_NAMES
	#undef ARGUMENTS_SPECIALIZATION

	#define RETURN_TYPE					ReturnType
	#define RETURN_TYPE_TEMPLATE		typename RETURN_TYPE
	#define COMMA_SEPARATOR				,
	#define ARGUMENTS_TYPES				Arg1Type, Arg2Type
	#define ARGUMENTS_TYPES_TEMPLATE	typename Arg1Type, typename Arg2Type
	#define ARGUMENTS_TYPES_NAMES		Arg1Type a1, Arg2Type a2
	#define ARGUMENTS_NAMES				a1, a2
	#define ARGUMENTS_SPECIALIZATION	< RETURN_TYPE, Arg1Type, Arg2Type, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType >

	#include "Event_template.h"

	// 3 arguments specialization

	#undef RETURN_TYPE
	#undef RETURN_TYPE_TEMPLATE
	#undef COMMA_SEPARATOR
	#undef ARGUMENTS_TYPES
	#undef ARGUMENTS_TYPES_TEMPLATE
	#undef ARGUMENTS_TYPES_NAMES
	#undef ARGUMENTS_NAMES
	#undef ARGUMENTS_SPECIALIZATION

	#define RETURN_TYPE					ReturnType
	#define RETURN_TYPE_TEMPLATE		typename RETURN_TYPE
	#define COMMA_SEPARATOR				,
	#define ARGUMENTS_TYPES				Arg1Type, Arg2Type, Arg3Type
	#define ARGUMENTS_TYPES_TEMPLATE	typename Arg1Type, typename Arg2Type, typename Arg3Type
	#define ARGUMENTS_TYPES_NAMES		Arg1Type a1, Arg2Type a2, Arg3Type a3
	#define ARGUMENTS_NAMES				a1, a2, a3
	#define ARGUMENTS_SPECIALIZATION	< RETURN_TYPE, Arg1Type, Arg2Type, Arg3Type, NullType, NullType, NullType, NullType, NullType, NullType, NullType >

	#include "Event_template.h"

	// 4 arguments specialization

	#undef RETURN_TYPE
	#undef RETURN_TYPE_TEMPLATE
	#undef COMMA_SEPARATOR
	#undef ARGUMENTS_TYPES
	#undef ARGUMENTS_TYPES_TEMPLATE
	#undef ARGUMENTS_TYPES_NAMES
	#undef ARGUMENTS_NAMES
	#undef ARGUMENTS_SPECIALIZATION

	#define RETURN_TYPE					ReturnType
	#define RETURN_TYPE_TEMPLATE		typename RETURN_TYPE
	#define COMMA_SEPARATOR				,
	#define ARGUMENTS_TYPES				Arg1Type, Arg2Type, Arg3Type, Arg4Type
	#define ARGUMENTS_TYPES_TEMPLATE	typename Arg1Type, typename Arg2Type, typename Arg3Type, typename Arg4Type
	#define ARGUMENTS_TYPES_NAMES		Arg1Type a1, Arg2Type a2, Arg3Type a3, Arg4Type a4
	#define ARGUMENTS_NAMES				a1, a2, a3, a4
	#define ARGUMENTS_SPECIALIZATION	< RETURN_TYPE, Arg1Type, Arg2Type, Arg3Type, Arg4Type, NullType, NullType, NullType, NullType, NullType, NullType >

	#include "Event_template.h"

	// 5 arguments specialization

	#undef RETURN_TYPE
	#undef RETURN_TYPE_TEMPLATE
	#undef COMMA_SEPARATOR
	#undef ARGUMENTS_TYPES
	#undef ARGUMENTS_TYPES_TEMPLATE
	#undef ARGUMENTS_TYPES_NAMES
	#undef ARGUMENTS_NAMES
	#undef ARGUMENTS_SPECIALIZATION

	#define RETURN_TYPE					ReturnType
	#define RETURN_TYPE_TEMPLATE		typename RETURN_TYPE
	#define COMMA_SEPARATOR				,
	#define ARGUMENTS_TYPES				Arg1Type, Arg2Type, Arg3Type, Arg4Type, Arg5Type
	#define ARGUMENTS_TYPES_TEMPLATE	typename Arg1Type, typename Arg2Type, typename Arg3Type, typename Arg4Type, typename Arg5Type
	#define ARGUMENTS_TYPES_NAMES		Arg1Type a1, Arg2Type a2, Arg3Type a3, Arg4Type a4, Arg5Type a5
	#define ARGUMENTS_NAMES				a1, a2, a3, a4, a5
	#define ARGUMENTS_SPECIALIZATION	< RETURN_TYPE, Arg1Type, Arg2Type, Arg3Type, Arg4Type, Arg5Type, NullType, NullType, NullType, NullType, NullType >

	#include "Event_template.h"

	// 6 arguments specialization

	#undef RETURN_TYPE
	#undef RETURN_TYPE_TEMPLATE
	#undef COMMA_SEPARATOR
	#undef ARGUMENTS_TYPES
	#undef ARGUMENTS_TYPES_TEMPLATE
	#undef ARGUMENTS_TYPES_NAMES
	#undef ARGUMENTS_NAMES
	#undef ARGUMENTS_SPECIALIZATION

	#define RETURN_TYPE					ReturnType
	#define RETURN_TYPE_TEMPLATE		typename RETURN_TYPE
	#define COMMA_SEPARATOR				,
	#define ARGUMENTS_TYPES				Arg1Type, Arg2Type, Arg3Type, Arg4Type, Arg5Type, Arg6Type
	#define ARGUMENTS_TYPES_TEMPLATE	typename Arg1Type, typename Arg2Type, typename Arg3Type, typename Arg4Type, typename Arg5Type, typename Arg6Type
	#define ARGUMENTS_TYPES_NAMES		Arg1Type a1, Arg2Type a2, Arg3Type a3, Arg4Type a4, Arg5Type a5, Arg6Type a6
	#define ARGUMENTS_NAMES				a1, a2, a3, a4, a5, a6
	#define ARGUMENTS_SPECIALIZATION	< RETURN_TYPE, Arg1Type, Arg2Type, Arg3Type, Arg4Type, Arg5Type, Arg6Type, NullType, NullType, NullType, NullType >

	#include "Event_template.h"

	// 7 arguments specialization

	#undef RETURN_TYPE
	#undef RETURN_TYPE_TEMPLATE
	#undef COMMA_SEPARATOR
	#undef ARGUMENTS_TYPES
	#undef ARGUMENTS_TYPES_TEMPLATE
	#undef ARGUMENTS_TYPES_NAMES
	#undef ARGUMENTS_NAMES
	#undef ARGUMENTS_SPECIALIZATION

	#define RETURN_TYPE					ReturnType
	#define RETURN_TYPE_TEMPLATE		typename RETURN_TYPE
	#define COMMA_SEPARATOR				,
	#define ARGUMENTS_TYPES				Arg1Type, Arg2Type, Arg3Type, Arg4Type, Arg5Type, Arg6Type, Arg7Type
	#define ARGUMENTS_TYPES_TEMPLATE	typename Arg1Type, typename Arg2Type, typename Arg3Type, typename Arg4Type, typename Arg5Type, typename Arg6Type, typename Arg7Type
	#define ARGUMENTS_TYPES_NAMES		Arg1Type a1, Arg2Type a2, Arg3Type a3, Arg4Type a4, Arg5Type a5, Arg6Type a6, Arg7Type a7
	#define ARGUMENTS_NAMES				a1, a2, a3, a4, a5, a6, a7
	#define ARGUMENTS_SPECIALIZATION	< RETURN_TYPE, Arg1Type, Arg2Type, Arg3Type, Arg4Type, Arg5Type, Arg6Type, Arg7Type, NullType, NullType, NullType >

	#include "Event_template.h"

	// 8 arguments specialization

	#undef RETURN_TYPE
	#undef RETURN_TYPE_TEMPLATE
	#undef COMMA_SEPARATOR
	#undef ARGUMENTS_TYPES
	#undef ARGUMENTS_TYPES_TEMPLATE
	#undef ARGUMENTS_TYPES_NAMES
	#undef ARGUMENTS_NAMES
	#undef ARGUMENTS_SPECIALIZATION

	#define RETURN_TYPE					ReturnType
	#define RETURN_TYPE_TEMPLATE		typename RETURN_TYPE
	#define COMMA_SEPARATOR				,
	#define ARGUMENTS_TYPES				Arg1Type, Arg2Type, Arg3Type, Arg4Type, Arg5Type, Arg6Type, Arg7Type, Arg8Type
	#define ARGUMENTS_TYPES_TEMPLATE	typename Arg1Type, typename Arg2Type, typename Arg3Type, typename Arg4Type, typename Arg5Type, typename Arg6Type, typename Arg7Type, typename Arg8Type
	#define ARGUMENTS_TYPES_NAMES		Arg1Type a1, Arg2Type a2, Arg3Type a3, Arg4Type a4, Arg5Type a5, Arg6Type a6, Arg7Type a7, Arg8Type a8
	#define ARGUMENTS_NAMES				a1, a2, a3, a4, a5, a6, a7, a8
	#define ARGUMENTS_SPECIALIZATION	< RETURN_TYPE, Arg1Type, Arg2Type, Arg3Type, Arg4Type, Arg5Type, Arg6Type, Arg7Type, Arg8Type, NullType, NullType >

	#include "Event_template.h"

	// 9 arguments specialization

	#undef RETURN_TYPE
	#undef RETURN_TYPE_TEMPLATE
	#undef COMMA_SEPARATOR
	#undef ARGUMENTS_TYPES
	#undef ARGUMENTS_TYPES_TEMPLATE
	#undef ARGUMENTS_TYPES_NAMES
	#undef ARGUMENTS_NAMES
	#undef ARGUMENTS_SPECIALIZATION

	#define RETURN_TYPE					ReturnType
	#define RETURN_TYPE_TEMPLATE		typename RETURN_TYPE
	#define COMMA_SEPARATOR				,
	#define ARGUMENTS_TYPES				Arg1Type, Arg2Type, Arg3Type, Arg4Type, Arg5Type, Arg6Type, Arg7Type, Arg8Type, Arg9Type
	#define ARGUMENTS_TYPES_TEMPLATE	typename Arg1Type, typename Arg2Type, typename Arg3Type, typename Arg4Type, typename Arg5Type, typename Arg6Type, typename Arg7Type, typename Arg8Type, typename Arg9Type
	#define ARGUMENTS_TYPES_NAMES		Arg1Type a1, Arg2Type a2, Arg3Type a3, Arg4Type a4, Arg5Type a5, Arg6Type a6, Arg7Type a7, Arg8Type a8, Arg9Type a9
	#define ARGUMENTS_NAMES				a1, a2, a3, a4, a5, a6, a7, a8, a9
	#define ARGUMENTS_SPECIALIZATION	< RETURN_TYPE, Arg1Type, Arg2Type, Arg3Type, Arg4Type, Arg5Type, Arg6Type, Arg7Type, Arg8Type, Arg9Type, NullType >

	#include "Event_template.h"

} // end namespace CORE

#endif
